﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IndignadoFramework.BackBone.Model;
using IndignadoFramework.BackBone.DTO;
using IndignadoFramework.DataAccessLayer.EntityModels;

namespace IndignadoFramework.BackBone.InternalServices.Implementacion
{
    public class ChatServicesImpl : ChatServices
    {
        public int initSesionChat(int MovimientoId, int UsuarioSolicitanteId, int UsuarioReceptorId)
        {
            // Busco si no hay una sesion abierta disponible
            IndignadoFrameworkEntities context = new IndignadoFrameworkEntities();
            IQueryable<SesionChat> chatEntity = from c in context.Chat
                                                where c.MovimientoId == MovimientoId
                                                    && c.SesionChatCerrada == false
                                                    && ((c.UsuarioSolicitanteId == UsuarioSolicitanteId && c.UsuarioReceptorId == UsuarioReceptorId) ||
                                                        (c.UsuarioSolicitanteId == UsuarioReceptorId && c.UsuarioReceptorId == UsuarioSolicitanteId))
                                                select c;
            if (chatEntity.Any())
            {
                SesionChat openedChat = chatEntity.First();
                // Si no esta aceptada, la acepto y guardo los cambios
                if (!openedChat.SesionChatAceptada && !openedChat.UsuarioSolicitanteId.Equals(UsuarioSolicitanteId))
                {
                    openedChat.SesionChatAceptada = true;
                    context.SaveChanges();
                }
                return openedChat.Id;
            }
            else
            {
                // Como no hay una sesion abierta, creo una nueva
                SesionChat chat = new SesionChat();
                chat.MovimientoId = MovimientoId;
                chat.UsuarioSolicitanteId = UsuarioSolicitanteId;
                chat.UsuarioReceptorId = UsuarioReceptorId;
                chat.SesionChatAceptada = false;
                chat.SesionChatCerrada = false;
                chat.SesionChatFechaCreada = DateTime.Now;
                context.AddObject("Chat", chat);
                context.SaveChanges();
                return chat.Id;
            }
        }

        public bool closeSesionChat(int MovimientoId, int SesionChatId)
        {
            IndignadoFrameworkEntities context = new IndignadoFrameworkEntities();
            IQueryable<SesionChat> chatEntity = from c in context.Chat
                                                      where c.MovimientoId == MovimientoId
                                                         && c.Id == SesionChatId
                                                      select c;
            if (!chatEntity.Any())
            {
                return false;
            }
            else
            {
                SesionChat chat = chatEntity.First();
                chat.SesionChatCerrada = true;
                // Construyo el mensaje de cierre de sesion
                Mensaje msj = new Mensaje();
                msj.SesionChatId = SesionChatId;
                msj.MovimientoId = MovimientoId;
                msj.MensajeEmisorNombre = "Close";
                msj.MensajeFechaEnvio = DateTime.Now;
                msj.MensajeTexto = "/close";
                chat.Mensaje.Add(msj);
                context.SaveChanges();
                return true;
            }
        }

        public void addMensajeChat(MensajeModel msj)
        {
            Mensaje mensajeEntity = new Mensaje();
            AutoMapper.Mapper.CreateMap<MensajeModel, Mensaje>();
            mensajeEntity = AutoMapper.Mapper.Map(msj, mensajeEntity);
            IndignadoFrameworkEntities context = new IndignadoFrameworkEntities();
            context.AddObject("Mensajes", mensajeEntity);
            context.SaveChanges();
        }

        public IEnumerable<MensajeModelDTO> getMensajes(int MovimientoId, int ChatSessionId, int UltimoMensajeId)
        {
            List<MensajeModelDTO> mensajes = new List<MensajeModelDTO>();
            IndignadoFrameworkEntities context = new IndignadoFrameworkEntities();
            IQueryable<Mensaje> mensajesEntity = from m in context.Mensajes
                                                     where m.MovimientoId == MovimientoId
                                                         && m.SesionChatId == ChatSessionId
                                                         && m.Id > UltimoMensajeId
                                                     select m;
            foreach (Mensaje msj in mensajesEntity)
            {
                MensajeModelDTO mensaje = new MensajeModelDTO();
                mensaje.Id = msj.Id;
                mensaje.MensajeFechaEnvio = msj.MensajeFechaEnvio.ToString();
                mensaje.MensajeTexto = msj.MensajeTexto;
                mensaje.SesionChatId = msj.SesionChatId;
                mensaje.MensajeEmisorNombre = msj.MensajeEmisorNombre;
                mensajes.Add(mensaje);
            }
            return mensajes;
        }

        public IEnumerable<UsuarioChatModelDTO> getUsuariosConectados(int? MovimientoId, int UsuarioId)
        {
            List<UsuarioChatModelDTO> usuarios = new List<UsuarioChatModelDTO>();
            IndignadoFrameworkEntities context = new IndignadoFrameworkEntities();
            IQueryable<Usuario> usuariosEntity;
            if (MovimientoId.HasValue)
            {
                usuariosEntity = from u in context.Usuarios
                                 where u.MovimientoId == MovimientoId.Value
                                    && u.UsuarioDadoBaja == false
                                    && u.UsuarioLogueado == true
                                    && u.Id != UsuarioId
                                 select u;
            }
            else
            {
                usuariosEntity = from u in context.Usuarios
                                 where u.UsuarioDadoBaja == false
                                    && u.UsuarioLogueado == true
                                    && u.Id != UsuarioId
                                 select u;
            }
            foreach (Usuario u in usuariosEntity)
            {
                if (!tienenSesionAbierta(MovimientoId, UsuarioId, u.Id))
                {
                    UsuarioChatModelDTO usuario = new UsuarioChatModelDTO();
                    AutoMapper.Mapper.CreateMap<Usuario, UsuarioChatModelDTO>();
                    usuario = AutoMapper.Mapper.Map(u, usuario);
                    usuarios.Add(usuario);
                }
            }
            return usuarios;
        }

        // Funcion que determina si dos usuarios tienen una sesion de chat abierta
        bool tienenSesionAbierta(int? MovimientoId, int id1, int id2)
        {
            IndignadoFrameworkEntities context = new IndignadoFrameworkEntities();
            IQueryable<SesionChat> sesionesEntity;
            if (MovimientoId.HasValue)
            {
                sesionesEntity = from s in context.Chat
                                 where s.MovimientoId == MovimientoId.Value
                                     && s.SesionChatCerrada == false
                                     && ((s.UsuarioReceptorId == id1 && s.UsuarioSolicitanteId == id2) ||
                                        (s.UsuarioReceptorId == id2 && s.UsuarioSolicitanteId == id1))
                                 select s;
            }
            else
            {
                sesionesEntity = from s in context.Chat
                                 where s.SesionChatCerrada == false
                                     && ((s.UsuarioReceptorId == id1 && s.UsuarioSolicitanteId == id2) ||
                                        (s.UsuarioReceptorId == id2 && s.UsuarioSolicitanteId == id1))
                                 select s;
            }
            return sesionesEntity.Any();
        }

        public IEnumerable<SesionChatModelDTO> getSesionChatAbiertas(int? MovimientoId, int UsuarioId)
        {
            List<SesionChatModelDTO> sesiones = new List<SesionChatModelDTO>();
            IndignadoFrameworkEntities context = new IndignadoFrameworkEntities();
            IQueryable<SesionChat> sesionesEntity;
            if (MovimientoId.HasValue)
            {
                sesionesEntity = from s in context.Chat
                                 where s.MovimientoId == MovimientoId.Value
                                     && s.SesionChatCerrada == false
                                     && s.SesionChatAceptada == true
                                     && (s.UsuarioReceptorId == UsuarioId || s.UsuarioSolicitanteId == UsuarioId)
                                 select s;
            }
            else
            {
                sesionesEntity = from s in context.Chat
                                 where s.SesionChatCerrada == false
                                     && s.SesionChatAceptada == true
                                     && (s.UsuarioReceptorId == UsuarioId || s.UsuarioSolicitanteId == UsuarioId)
                                 select s;
            }
            foreach (SesionChat s in sesionesEntity)
            {
                SesionChatModelDTO sesion = new SesionChatModelDTO();
                AutoMapper.Mapper.CreateMap<SesionChat, SesionChatModelDTO>();
                sesion = AutoMapper.Mapper.Map(s, sesion);
                if (s.UsuarioSolicitanteId.Equals(UsuarioId))
                {
                    sesion.UsuarioSolicitanteId = s.UsuarioReceptorId;
                    sesion.UsuarioSolicitanteNombre = s.UsuarioReceptor.UsuarioNombre;
                    sesion.UsuarioReceptorId = s.UsuarioSolicitanteId;
                }
                else
                {
                    sesion.UsuarioSolicitanteNombre = s.UsuarioSolicitante.UsuarioNombre;
                }
                sesiones.Add(sesion);
            }
            return sesiones;
        }

        public IEnumerable<SesionChatModelDTO> getSesionChatPendientes(int? MovimientoId, int UsuarioId)
        {
            List<SesionChatModelDTO> sesiones = new List<SesionChatModelDTO>();
            IndignadoFrameworkEntities context = new IndignadoFrameworkEntities();
            IQueryable<SesionChat> sesionesEntity;
            if (MovimientoId.HasValue)
            {
                sesionesEntity = from s in context.Chat
                                 where s.MovimientoId == MovimientoId.Value
                                     && s.SesionChatCerrada == false
                                     && s.SesionChatAceptada == false
                                     && (s.UsuarioReceptorId == UsuarioId || s.UsuarioSolicitanteId == UsuarioId)
                                 select s;
            }
            else
            {
                sesionesEntity = from s in context.Chat
                                 where s.SesionChatCerrada == false
                                     && s.SesionChatAceptada == false
                                     && (s.UsuarioReceptorId == UsuarioId || s.UsuarioSolicitanteId == UsuarioId)
                                 select s;
            }
            foreach (SesionChat s in sesionesEntity)
            {
                SesionChatModelDTO sesion = new SesionChatModelDTO();
                AutoMapper.Mapper.CreateMap<SesionChat, SesionChatModelDTO>();
                sesion = AutoMapper.Mapper.Map(s, sesion);
                if (s.UsuarioSolicitanteId.Equals(UsuarioId))
                {
                    sesion.UsuarioSolicitanteId = s.UsuarioReceptorId;
                    sesion.UsuarioSolicitanteNombre = s.UsuarioReceptor.UsuarioNombre;
                    sesion.UsuarioReceptorId = s.UsuarioSolicitanteId;
                }
                else
                {
                    sesion.UsuarioSolicitanteNombre = s.UsuarioSolicitante.UsuarioNombre;
                }
                sesiones.Add(sesion);
            }
            return sesiones;
        }
    }
}
